package server.service;

import common.Message;

import common.MessageStatus;
import common.User;
import database.DAO.UserLoginStatusDAO;
import database.service.OfflineMessageService;
import database.service.RelationService;
import database.service.UserLoginStatusService;
import database.service.UserService;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Iterator;
import java.util.List;

public class ServerService {
    private static ServerSocket server;
    private static UserService userService=new UserService();
    private static UserLoginStatusService userLoginStatusService=new UserLoginStatusService();
    private static OfflineMessageService offlineMessagesService=new OfflineMessageService();

    private static RelationService relationService=new RelationService();

    public void listening(){
        try {
            server=new ServerSocket(9999);

            //一直监听
            while(true) {
                System.out.println("正在监听9999端口");
                Socket socket = server.accept();

                ObjectInputStream objIn = new ObjectInputStream(socket.getInputStream());
                ObjectOutputStream objOut = new ObjectOutputStream(socket.getOutputStream());

                User user= (User)objIn.readObject();

                //待发送
                Message message = new Message();
                User dbUser=userService.queryByAccount(user.getUser_account());


                if(dbUser==null){
                    System.out.println("账号:"+user.getUser_account()+" 不存在，无法登录");
                    message.setType(MessageStatus.USERID_ERROR);
                    objOut.writeObject(message);
                    objOut.flush();
                    socket.close();
                    continue;
                }

                message.setSender(dbUser.getUser_name());
                if(!dbUser.getUser_password().equals(user.getUser_password())){
                    System.out.println(dbUser.getUser_name()+" 密码错误，无法登录");
                    message.setType(MessageStatus.PASSWORD_ERROR);
                    objOut.writeObject(message);
                    objOut.flush();
                    socket.close();
                    continue;
                }

                if(userLoginStatusService.queryUserLoginStatusByUserName(dbUser.getUser_name())){
                    System.out.println(dbUser.getUser_name()+" 已经在线，不能再登录");
                    message.setType(MessageStatus.IS_ONLINE);
                    objOut.writeObject(message);
                    objOut.flush();
                    socket.close();
                    continue;
                }
                userLoginStatusService.updateUserLoginStatusByUserName(dbUser.getUser_name(),true);

                //发送成功message给Client
                System.out.println(dbUser.getUser_name()+" 成功登录");
                message.setType(MessageStatus.LOGIN_SUCCEED);


                objOut.writeObject(message);
                objOut.flush();

                //发送离线消息
                List<Object> messages = offlineMessagesService.queryByName(dbUser.getUser_name());
                if(messages.size()!=0){
                    System.out.println(dbUser.getUser_name()+" 有"+messages.size()+"条离线消息，现在立马发送");
                    sendOffLineMessage(dbUser.getUser_name(),messages,socket);
                }


                //开启线程

                UserThread userThread = new UserThread(dbUser.getUser_name(), socket,dbUser.getUser_account());
                userThread.start();
                SocketThreadManager.addUserThread(dbUser.getUser_name(),userThread);


            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {

            //关闭服务器
            try {
                System.out.println("服务器关闭");
                server.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void offline(String userName){
        userLoginStatusService.updateUserLoginStatusByUserName(userName,false);
    }
    public static void saveOfflineMessageToDB(Message offlineMessage,String getter,String storeToFilePath){
        if(storeToFilePath!=null){
            saveFileToServerLocal(offlineMessage,storeToFilePath);
            offlineMessage.setFileBytes(storeToFilePath.getBytes());
        }
        int row = offlineMessagesService.updateOfflineMessageByUserName(getter,offlineMessage);
        if(row!=0){
            System.out.println(offlineMessage.getSender()+"发给"+getter+"的消息成功保存到数据库");
        }else {


        }
    }
    public static void saveFileToServerLocal(Message message,String storeToFilePath) {
        File file = new File(storeToFilePath);
        if(file.exists()){
            System.out.println("server本地已经有该文件，不用再保存--"+message.getFileName());
            return;
        }

        System.out.println("保存"+message.getSender()+"发送的文件到server本地:"+storeToFilePath);
        try {
            FileOutputStream fileOut =null;
            try {
                fileOut = new FileOutputStream(storeToFilePath);
                fileOut.write(message.getFileBytes());
                fileOut.flush();
                System.out.println("保存成功");
            }finally {
                if(fileOut!=null){
                    fileOut.close();
                }
            }
        } catch (Exception e) {
            System.out.println("保存失败");
            throw new RuntimeException(e);
        }
    }

    public void sendLocalFileToClient(Message message){
        String storeToFilePath=new String(message.getFileBytes());
        System.out.println("发送"+message.getSender()+"发送的离线文件--server本地文件到目标client: "+storeToFilePath);
        try {
            FileInputStream fileIn =null;
            try {
                fileIn = new FileInputStream(storeToFilePath);
                message.setFileBytes(fileIn.readAllBytes());
                System.out.println("离线文件的长度："+message.getFileBytes().length);
                System.out.println("发送成功");
            }finally {
                if(fileIn!=null){
                    fileIn.close();
                }
            }
        } catch (Exception e) {
            System.out.println("发送失败");
            throw new RuntimeException(e);
        }
    }

    public static String getFriendListString(String userName){
        String linkNameAndStatus="-";
        String separator=" ";
        StringBuilder res = new StringBuilder();
        List<Object[]> friendList = relationService.queryFriendListByUserName(userName);

        for(Object[] friend:friendList){
            res.append(friend[0]+linkNameAndStatus+ UserLoginStatusDAO.isOnline((Boolean)friend[1]) +separator);
        }
        return res.toString();
    }
    public static List<Object> getGroupNumbersList(String groupName){
        return relationService.queryGroupNumbersListByUserName(groupName);
    }
    private void sendOffLineMessage(String userName,List<Object> messages,Socket socket) throws IOException {
            Iterator<Object> iterator = messages.iterator();
            //ObjectOutputStream objOut = new ObjectOutputStream(socket.getOutputStream());
            while (iterator.hasNext()) {
                //这个输出流在while外面创建会问题，这个用户的客户端出现大量异常
                //java.io.StreamCorruptedException: invalid stream header: 7371007E

                ObjectOutputStream objOut = new ObjectOutputStream(socket.getOutputStream());
                Message message = (Message) iterator.next();

//                if(message.getType()==MessageStatus.GROUP_CHAT||
//                        message.getType()==MessageStatus.PRIVATE_CHAT){
//                    message.setType_of_chat(MessageStatus.TEXT_CHAT);
//                }else if(message.getType()==MessageStatus.GROUP_SEND_FILE||
//                        message.getType()==MessageStatus.PRIVATE_SEND_FILE){
//                    message.setType_of_chat(MessageStatus.FILE_CHAT);
//                }

                if(message.getType()==MessageStatus.GROUP_SEND_FILE||
                        message.getType()==MessageStatus.PRIVATE_SEND_FILE){
                    sendLocalFileToClient(message);
                }

                objOut.writeObject(message);
                objOut.flush();
            }
            offlineMessagesService.deleteOfflineMessageByUserName(userName);
            System.out.println(userName+" 的离线消息发送完毕");
    }
}
